#include "stdafx.h"
#include "CppUnitTest.h"

#include "TestFiles.h"

#include "ImageProcessFile.h"
#include "UnitTestValidStep.h"
#include "UnitTestValidAnalysisStep.h"

#include "ImageProcSteps.h"


using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace PluginICProcStepsTest
{
	TEST_CLASS(ImageProcStepsTest)
	{
	private:
		ImageProcSteps *_steps;

	public:
		TEST_METHOD_INITIALIZE(InitPluginICProcStepsTest)
		{
			_steps = new ImageProcSteps();
		}

		TEST_METHOD_CLEANUP(DeinitPluginICProcStepsTest)
		{
			if (_steps != '\0')
				delete _steps;
			_steps = '\0';
		}
		
		TEST_METHOD(CreateImageProcStepsTest)
		{
			Assert::IsNotNull(_steps);
			Assert::IsFalse(_steps->Validate());	//cannot validate an empty list
		}

		TEST_METHOD(AddStepTest)
		{
			Assert::IsFalse(_steps->IsValid());

			UnitTestValidStep *step1 = new UnitTestValidStep(0);
			Assert::IsTrue(step1->Validate());
			UnitTestValidStep *step2 = new UnitTestValidStep(1);
			Assert::IsTrue(step2->Validate());
			UnitTestValidAnalysisStep *step3 = new UnitTestValidAnalysisStep(2);
			Assert::IsTrue(step3->Validate());
		
			Assert::IsTrue(_steps->SetImageIntermediatePathFilename(TestFiles::UnitTestIntermediateImageFilewStr));

			Assert::AreEqual( ImageProcSteps::InvalidStepCount, _steps->GetStepCount());
			Assert::IsTrue(_steps->AddStep(step1));	
			Assert::IsTrue(_steps->AddStep(step2));	

			Assert::IsFalse( _steps->AddStep(step2));	//cannot add duplicates
			Assert::IsFalse( _steps->Validate());		//must contain an ImageProcStepAnalysis

			Assert::IsNull(_steps->GetStep(0));
			Assert::IsTrue(_steps->AddStep(step3));	
			Assert::IsTrue( _steps->Validate());	
			Assert::IsTrue( _steps->IsValid());

			Assert::AreEqual(TestFiles::UnitTestIntermediateImageFileStr, _steps->GetImageIntermediatePathFilename());

			Assert::AreEqual( 3, _steps->GetStepCount());

			Assert::IsNotNull(_steps->GetStep(0));
			Assert::IsNotNull(_steps->GetStep(1));
			Assert::IsNotNull(_steps->GetStep(2));
			Assert::IsNull (_steps->GetStep(3));
			Assert::IsNull (_steps->GetStep(-1));

			Assert::IsTrue(_steps->ClearAllSteps());
		}

		TEST_METHOD(SetImagePathFilenameTest)
		{
				TiXmlElement  *badimage = new TiXmlElement("test");
				TiXmlElement  *emptyimage = new TiXmlElement(ImageProcessFile::xmlImage);

				TiXmlElement  *image = new TiXmlElement(ImageProcessFile::xmlImage);
				TiXmlText     *txt = new TiXmlText( TestFiles::UnitTestImageStr );
				image->LinkEndChild( txt );
		
				UnitTestValidAnalysisStep *step = new UnitTestValidAnalysisStep(0);
				Assert::IsTrue(step->Validate());

				Assert::IsTrue(_steps->SetImageIntermediatePathFilename(TestFiles::UnitTestIntermediateImageFilewStr));
				Assert::IsTrue( _steps->AddStep(step));

				Assert::IsFalse(_steps->SetImagePathFilename( TestFiles::UnitTestImageDirwStr, image));		//must validate first
				Assert::IsTrue(_steps->Validate());

				Assert::IsFalse( _steps->SetImagePathFilename( '\0', image));								//Dir is null
				Assert::IsFalse( _steps->SetImagePathFilename(TestFiles::UnitTestImageDirwStr, '\0'));		//image is null
				Assert::IsFalse( _steps->SetImagePathFilename('\0', '\0'));									//image is null
				Assert::IsFalse( _steps->SetImagePathFilename( L"xxx", image));								//Invalid Dir
				Assert::IsFalse(_steps->SetImagePathFilename(TestFiles::UnitTestImageDirwStr, badimage));	//image is bad
				Assert::IsFalse( _steps->SetImagePathFilename(TestFiles::UnitTestImageDirwStr, emptyimage));//image has no text

				Assert::IsTrue( _steps->SetImagePathFilename( TestFiles::UnitTestImageDirwStr, image));		//ok

				std::string imagefile(TestFiles::UnitTestImagePathFilenameStr);
				Assert::IsTrue( _steps->GetImagePathFilename() == imagefile);

				Assert::IsTrue(_steps->ClearAllSteps());
		
				delete image;
				delete emptyimage;
				delete badimage;
		}

		TEST_METHOD(GetNextStepNoneTest)
		{
			TiXmlElement  *image = new TiXmlElement(ImageProcessFile::xmlImage);
			TiXmlText     *txt = new TiXmlText( TestFiles::UnitTestImageStr );
			image->LinkEndChild( txt );
		
			UnitTestValidAnalysisStep *step = new UnitTestValidAnalysisStep(0);
			Assert::IsTrue(step->Validate());

			Assert::IsTrue(_steps->SetImageIntermediatePathFilename(TestFiles::UnitTestIntermediateImageFilewStr));
			Assert::IsFalse( _steps->Validate());		//no steps

			Assert::IsFalse( (_steps->GetFirstStep(TestFiles::UnitTestImageDirwStr, image) == step));		
			Assert::IsNull(_steps->GetNextStep());

			Assert::IsFalse(_steps->ClearAllSteps());	//no steps to clear
			delete image;
		}

		TEST_METHOD(GetNextStepOneTest)
		{
			TiXmlElement  *badimage = new TiXmlElement("test");
			TiXmlElement  *emptyimage = new TiXmlElement(ImageProcessFile::xmlImage);

			TiXmlElement  *image = new TiXmlElement(ImageProcessFile::xmlImage);
			TiXmlText     *txt = new TiXmlText( TestFiles::UnitTestImageStr );
			image->LinkEndChild( txt );
		
			UnitTestValidAnalysisStep *step = new UnitTestValidAnalysisStep(0);
			Assert::IsTrue(step->Validate());

			Assert::IsTrue( _steps->SetImageIntermediatePathFilename(TestFiles::UnitTestIntermediateImageFilewStr));
			Assert::IsTrue( _steps->AddStep(step));
			Assert::IsTrue( _steps->Validate());

			Assert::IsNull( _steps->GetFirstStep('\0', image));
			Assert::IsNull(_steps->GetFirstStep('\0', '\0'));
			Assert::IsNull(_steps->GetFirstStep(TestFiles::UnitTestImageDirwStr, badimage));
			Assert::IsNull(_steps->GetFirstStep(TestFiles::UnitTestImageDirwStr, emptyimage));

			Assert::IsTrue((_steps->GetFirstStep(TestFiles::UnitTestImageDirwStr, image) == step));		
			Assert::IsNull(_steps->GetNextStep());		

			Assert::IsTrue( _steps->ClearAllSteps());

			delete image;
			delete emptyimage;
			delete badimage;
		}

		TEST_METHOD(GetNextStepThreeTest)
		{
			TiXmlElement  *image = new TiXmlElement(ImageProcessFile::xmlImage);
			TiXmlText     *txt = new TiXmlText( TestFiles::UnitTestImageStr );
			image->LinkEndChild( txt );
		
			UnitTestValidAnalysisStep *step0 = new UnitTestValidAnalysisStep(0);
			Assert::IsTrue( step0->Validate());
			UnitTestValidStep *step1 = new UnitTestValidStep(1);
			Assert::IsTrue(  step1->Validate());
			UnitTestValidStep *step2 = new UnitTestValidStep(2);
			Assert::IsTrue( step2->Validate());

			Assert::IsTrue( _steps->SetImageIntermediatePathFilename(TestFiles::UnitTestIntermediateImageFilewStr));
			Assert::IsTrue( _steps->AddStep(step0));
			Assert::IsTrue( _steps->AddStep(step1));
			Assert::IsTrue( _steps->AddStep(step2));
			Assert::IsTrue( _steps->Validate());

			Assert::AreEqual( 3, _steps->GetStepCount());

			Assert::IsTrue( (_steps->GetFirstStep(TestFiles::UnitTestImageDirwStr, image) == step0));		
			Assert::IsTrue((_steps->GetNextStep() == step1));		
			Assert::IsTrue( (_steps->GetNextStep() == step2));
			Assert::IsNull(_steps->GetNextStep());		

			Assert::IsTrue( _steps->ClearAllSteps());

			delete image;
		}

		TEST_METHOD(BadParamLoadStepsTest)
		{
			ImageProcStepLibs *Libs = '\0';
			Assert::IsNotNull(Libs = new ImageProcStepLibs());

			Assert::IsTrue( Libs->LoadLibs(TestFiles::UnitTestPluginDirwStr));	//add this directory to PATH
			Assert::AreEqual( 1, Libs->GetLibCount());

			ImageExpt *ief = '\0';

			Assert::IsNotNull((ief = ImageExpt::CreateImageExpt(TestFiles::UnitTestIEFwStr, '\0', L"unit test", L"default", ImageExpt::FromDefaults)));
			Assert::IsTrue( ief->SaveFile());
			Assert::IsTrue( ImageExptLib::IsFileExist(TestFiles::UnitTestIEFwStr));
			Assert::IsNotNull(ief->GetHeaderProcSteps() );

			Assert::IsFalse(_steps->LoadSteps('\0', Libs, TestFiles::UnitTestIntermediateImageFilewStr));
			Assert::IsFalse( _steps->LoadSteps(ief, '\0', TestFiles::UnitTestIntermediateImageFilewStr));	
			Assert::IsFalse( _steps->LoadSteps('\0', '\0', TestFiles::UnitTestIntermediateImageFilewStr));
			Assert::IsFalse( _steps->LoadSteps('\0', '\0', '\0'));
			Assert::IsFalse( _steps->ClearAllSteps());	//returns true if StepsCount() > 0

			Assert::IsTrue( Libs->ClearAllLibs());		//returns true if GetLibCount() > 0
			Assert::AreEqual(0, Libs->GetLibCount());

			if (ief != '\0')
				delete ief;
		}

		TEST_METHOD(LoadNoStepsTest)
		{
			ImageProcStepLibs *Libs = '\0';
			Assert::IsNotNull(Libs = new ImageProcStepLibs());

			Assert::IsTrue( Libs->LoadLibs(TestFiles::UnitTestPluginDirwStr));
			Assert::AreEqual( 1, Libs->GetLibCount());

			ImageExpt *ief = '\0';

			Assert::IsNotNull(ief = ImageExpt::CreateImageExpt(TestFiles::UnitTestIEFwStr, '\0', L"unit test", L"default", ImageExpt::FromDefaults));
			Assert::IsTrue( ief->SaveFile());
			Assert::IsTrue( ImageExptLib::IsFileExist(TestFiles::UnitTestIEFwStr));
			Assert::IsNotNull(ief->GetHeaderProcSteps());

			TiXmlElement *procStepsXml = ief->GetHeaderProcSteps();
			procStepsXml->SetAttribute(ImageProcStepLibAuto::attribImageDllDir, TestFiles::UnitTestPluginDirStr);
			procStepsXml->Clear();	//remove default analysis step

			Assert::IsFalse( _steps->LoadSteps(ief, Libs, TestFiles::UnitTestIntermediateImageFilewStr));		
			Assert::IsFalse( _steps->IsValid());		//no steps found				
			Assert::IsFalse( _steps->ClearAllSteps());	//returns true if StepsCount() > 0

			Assert::IsTrue( Libs->ClearAllLibs());		//returns true if GetLibCount() > 0
			Assert::AreEqual( 0, Libs->GetLibCount());

			if (ief != '\0')
				delete ief;
		}

		TEST_METHOD(LoadStepsNoStepNumTest)
		{
			ImageProcStepLibs *Libs = '\0';
			Assert::IsNotNull(Libs = new ImageProcStepLibs());

			Assert::IsTrue(Libs->LoadLibs(TestFiles::UnitTestPluginDirwStr));
			Assert::AreEqual( 1, Libs->GetLibCount());

			ImageExpt *ief = '\0';

			Assert::IsNotNull(ief = ImageExpt::CreateImageExpt(TestFiles::UnitTestIEFwStr, '\0', L"unit test", L"default", ImageExpt::FromDefaults));
			Assert::IsTrue( ief->SaveFile());
			Assert::IsTrue( ImageExptLib::IsFileExist(TestFiles::UnitTestIEFwStr));
			Assert::IsNotNull(ief->GetHeaderProcSteps());

			TiXmlElement *procStepsXml = ief->GetHeaderProcSteps();
			procStepsXml->SetAttribute(ImageProcStepLibAuto::attribImageDllDir, TestFiles::UnitTestPluginDirStr);
			procStepsXml->Clear();	//remove default analysis step

			TiXmlElement *procStepXml = TinyXmlLib::CreateSection (procStepsXml, ImageProcStep::xmlProcStep, "(give description)" );
			//procStepXml->SetAttribute("StepNum", 0);
			procStepXml->SetAttribute("LibName", "ImageProcSample.dll");
			procStepXml->SetAttribute("LibVer", "v1.0.0.0");
			procStepXml->SetAttribute("Iver", 1);
			procStepXml->SetAttribute("Function", "CalcAvBrightness");

			TiXmlElement *InputsXml = TinyXmlLib::CreateSection (procStepXml, ProcParamsInputs::xmlInputs, "CalcAvBrightness" );
			InputsXml->SetAttribute("Count", 1);

			TiXmlElement *ip1 = TinyXmlLib::CreateSection (InputsXml, IPluginICProcStepsParamXmlProcParam, "50" );
			ip1->SetAttribute("Name", "brightness");
			ip1->SetAttribute("Index", 0);
			ip1->SetAttribute("Type", "IntP");

			TiXmlElement *OutputsXml = TinyXmlLib::CreateSection (procStepXml, ProcParamsOutputs::xmlOutputs, "CalcAvBrightness" );
			OutputsXml->SetAttribute("Count", 1);

			TiXmlElement *op1 = TinyXmlLib::CreateSection (OutputsXml, IPluginICProcStepsParamXmlProcParam, "5" );
			op1->SetAttribute("Name", "Result");
			op1->SetAttribute("Index", 0);
			op1->SetAttribute("Type", "IntP");

			Assert::IsFalse(_steps->LoadSteps(ief, Libs, TestFiles::UnitTestIntermediateImageFilewStr));	//no stepCnt found
			Assert::IsFalse( _steps->IsValid());		//no valid steps				

			Assert::IsTrue(Libs->ClearAllLibs());		//returns true if GetLibCount() > 0
			Assert::AreEqual( 0, Libs->GetLibCount());

			if (ief != '\0')
				delete ief;
		}

		TEST_METHOD(LoadStepsBadLibXmlTest)
		{
			ImageProcStepLibs *Libs = '\0';
			Assert::IsNotNull (Libs = new ImageProcStepLibs());

			Assert::IsTrue( Libs->LoadLibs(TestFiles::UnitTestPluginDirwStr));
			Assert::AreEqual( 1, Libs->GetLibCount());

			ImageExpt *ief = '\0';

			Assert::IsNotNull (ief = ImageExpt::CreateImageExpt(TestFiles::UnitTestIEFwStr, '\0', L"unit test", L"default", ImageExpt::FromDefaults));
			Assert::IsTrue( ief->SaveFile());
			Assert::IsTrue( ImageExptLib::IsFileExist(TestFiles::UnitTestIEFwStr));
			Assert::IsNotNull(ief->GetHeaderProcSteps());

			TiXmlElement *procStepsXml = ief->GetHeaderProcSteps();
			procStepsXml->SetAttribute(ImageProcStepLibAuto::attribImageDllDir, TestFiles::UnitTestPluginDirStr);
			procStepsXml->Clear();	//remove default analysis step

			TiXmlElement *procStepXml = TinyXmlLib::CreateSection (procStepsXml, ImageProcStep::xmlProcStep, "(give description)" );
			procStepXml->SetAttribute("StepNum", 0);

			TiXmlElement *InputsXml = TinyXmlLib::CreateSection (procStepXml, ProcParamsInputs::xmlInputs, "CalcAvBrightness" );
			InputsXml->SetAttribute("Count", 1);

			TiXmlElement *ip1 = TinyXmlLib::CreateSection (InputsXml, IPluginICProcStepsParamXmlProcParam, "50" );
			ip1->SetAttribute("Name", "brightness");
			ip1->SetAttribute("Index", 0);
			ip1->SetAttribute("Type", "IntP");

			TiXmlElement *OutputsXml = TinyXmlLib::CreateSection (procStepXml, ProcParamsOutputs::xmlOutputs, "CalcAvBrightness" );
			OutputsXml->SetAttribute("Count", 1);

			TiXmlElement *op1 = TinyXmlLib::CreateSection (OutputsXml, IPluginICProcStepsParamXmlProcParam, "5" );
			op1->SetAttribute("Name", "Result");
			op1->SetAttribute("Index", 0);
			op1->SetAttribute("Type", "IntP");

			Assert::IsFalse( _steps->LoadSteps(ief, Libs, L"xxxx"));	//non existant intermed file	
			Assert::IsFalse( _steps->IsValid());	

			Assert::IsFalse( _steps->LoadSteps(ief, Libs, TestFiles::UnitTestIntermediateImageFilewStr));		//no lib name
			Assert::IsFalse(  _steps->IsValid());
			procStepXml->SetAttribute("LibName", "ImageProcSample.dll");
			Assert::IsFalse( _steps->LoadSteps(ief, Libs, TestFiles::UnitTestIntermediateImageFilewStr));		//no lib ver
			Assert::IsFalse( _steps->IsValid());
			procStepXml->SetAttribute("LibVer", "v1.0.0.0");
			Assert::IsFalse( _steps->LoadSteps(ief, Libs, TestFiles::UnitTestIntermediateImageFilewStr));		//no interface ver
			Assert::IsFalse(  _steps->IsValid());
			procStepXml->SetAttribute("IVer", 1);
			Assert::IsFalse( _steps->LoadSteps(ief, Libs, TestFiles::UnitTestIntermediateImageFilewStr));		//no function
			Assert::IsFalse( _steps->IsValid());
	
			Assert::IsFalse( _steps->ClearAllSteps());

			Assert::IsTrue( Libs->ClearAllLibs());		//returns true if GetLibCount() > 0
			Assert::AreEqual( 0, Libs->GetLibCount());

			if (ief != '\0')
				delete ief;
		}

		TEST_METHOD(LoadStepsNoAnalysisXmlTest)
		{
			ImageProcStepLibs *Libs = '\0';
			Assert::IsNotNull (Libs = new ImageProcStepLibs());

			Assert::IsTrue( Libs->LoadLibs(TestFiles::UnitTestPluginDirwStr));
			Assert::AreEqual( 1, Libs->GetLibCount());

			ImageExpt *ief = '\0';

			Assert::IsNotNull (ief = ImageExpt::CreateImageExpt(TestFiles::UnitTestIEFwStr, '\0', L"unit test", L"default", ImageExpt::FromDefaults));
			Assert::IsTrue( ief->SaveFile());
			Assert::IsTrue(ImageExptLib::IsFileExist(TestFiles::UnitTestIEFwStr));
			Assert::IsNotNull (ief->GetHeaderProcSteps());

			TiXmlElement *procStepsXml = ief->GetHeaderProcSteps();
			procStepsXml->SetAttribute(ImageProcStepLibAuto::attribImageDllDir, TestFiles::UnitTestPluginDirStr);
			procStepsXml->Clear();	//remove default analysis step

			TiXmlElement *procStepXml = TinyXmlLib::CreateSection (procStepsXml, ImageProcStep::xmlProcStep, "(give description)" );
			procStepXml->SetAttribute("StepNum", 0);
			procStepXml->SetAttribute("LibName", "ImageProcSample.dll");
			procStepXml->SetAttribute("LibVer", "v1.0.0.0");
			procStepXml->SetAttribute("IVer", 1);
			procStepXml->SetAttribute("Function", "CalcAvBrightness");

			TiXmlElement *InputsXml = TinyXmlLib::CreateSection (procStepXml, ProcParamsInputs::xmlInputs, "CalcAvBrightness" );
			InputsXml->SetAttribute("Count", 1);

			TiXmlElement *ip1 = TinyXmlLib::CreateSection (InputsXml, IPluginICProcStepsParamXmlProcParam, "50" );
			ip1->SetAttribute("Name", "brightness");
			ip1->SetAttribute("Index", 0);
			ip1->SetAttribute("Type", "IntP");

			TiXmlElement *OutputsXml = TinyXmlLib::CreateSection (procStepXml, ProcParamsOutputs::xmlOutputs, "CalcAvBrightness" );
			OutputsXml->SetAttribute("Count", 1);

			TiXmlElement *op1 = TinyXmlLib::CreateSection (OutputsXml, IPluginICProcStepsParamXmlProcParam, "1" );
			op1->SetAttribute("Name", "Result");
			op1->SetAttribute("Index", 0);
			op1->SetAttribute("Type", "IntP");

			Assert::IsFalse( _steps->LoadSteps(ief, Libs, TestFiles::UnitTestIntermediateImageFilewStr));		
			Assert::IsFalse( _steps->IsValid());			//no analysis step				
			Assert::IsTrue( _steps->ClearAllSteps());		//false if no steps, true because "CalcAvBrightness" set

			Assert::IsTrue( Libs->ClearAllLibs());			//returns true if GetLibCount() > 0
			Assert::AreEqual( 0, Libs->GetLibCount());

			if (ief != '\0')
				delete ief;
		}

		TEST_METHOD(Load1StepTest)
		{
			// 1. load  ImageProcSampleLib.dll from ImageProcStepsTest::ImageProcStepSampleLibPath (..\..\ThirdPartyLibs) - MUST BE IN PATH

			ImageProcStepLibs *Libs = '\0';
			Assert::IsNotNull (Libs = new ImageProcStepLibs());

			Assert::IsTrue( Libs->LoadLibs(TestFiles::UnitTestPluginDirwStr));
			Assert::AreEqual( 1, Libs->GetLibCount());		//ImageProcSampleLib.dll and ImageProcOpenCVLib.dll

			// 2. Create an Image Experiment File (IEF) called ImageExptLibTest::UnitTestIEFwStr () "..\\..\\UnitTestData\\Test.ief"

			ImageExpt *ief = '\0';

			Assert::IsNotNull (ief = ImageExpt::CreateImageExpt(TestFiles::UnitTestIEFwStr, '\0', L"unit test", L"default", ImageExpt::FromDefaults));
			Assert::IsTrue( ief->SaveFile());
			Assert::IsTrue(ImageExptLib::IsFileExist(TestFiles::UnitTestIEFwStr));
			Assert::IsNotNull (ief->GetHeaderProcSteps());

			TiXmlElement *procStepsXml = ief->GetHeaderProcSteps();
			procStepsXml->SetAttribute(ImageProcStepLibAuto::attribImageDllDir, TestFiles::UnitTestPluginDirStr);  
			procStepsXml->Clear();	//remove default analysis step

			// 3. Setup the ImageProcSteps section of the IEF so it contains the Step you want to test

			// 3a. Set the library details

			TiXmlElement *procStepXml = TinyXmlLib::CreateSection (procStepsXml, ImageProcStep::xmlProcStep, "(give description)" );
			procStepXml->SetAttribute("StepNum", 0);						//this is the first step
			procStepXml->SetAttribute("LibName", "ImageProcSample.dll");	//this is the library name - contains the function "CalcScore"
			procStepXml->SetAttribute("LibVer", "v1.0.0.0");				//this is the library version - should match setting in "ImageProcSample.dll"
			procStepXml->SetAttribute("IVer", 1);							//this is the library interface version - should match setting in "ImageProcSample.dll"

			// 3b. Set the name of a function in the above library - see ImageProcSampleLib.xml created when you run ImageProcSampleApp.exe
			//		<Step LibName="ImageProcSample.dll" LibVer="v1.0.0.0" IVer="1" Function="CalcScore" AnalysisStep="yes">
		
			procStepXml->SetAttribute("Function", "CalcScore");				//name of the function that forms the step

			// 3c. Set the inputs for the above function name - see ImageProcSampleLib.xml created when you run ImageProcSampleApp.exe	
			//        <Inputs Count="1">CalcScore
			//            <Param Name="brightness" Index="0" Type="IntP">50</Param>
			//        </Inputs>

			TiXmlElement *InputsXml = TinyXmlLib::CreateSection (procStepXml, ProcParamsInputs::xmlInputs, "CalcScore" );
			InputsXml->SetAttribute("Count", 1);							//there is only 1 input param

			TiXmlElement *ip1 = TinyXmlLib::CreateSection (InputsXml, IPluginICProcStepsParamXmlProcParam, "50" );
			ip1->SetAttribute("Name", "brightness");						//
			ip1->SetAttribute("Index", 0);
			ip1->SetAttribute("Type", "IntP");

			// 3d. Set the outputs for the above function name - see ImageProcSampleLib.xml created when you run ImageProcSampleApp.exe
			//        <Outputs Count="2">CalcScore
			//            <Param Name="Result" Index="0" Type="IntP">0</Param>
			//            <Param Name="Score" Index="1" Type="DoubleP">50.0</Param>
			//        </Outputs>
			//
			//  **** NOTE: Every step must have a "Result" output parameter and each collection of steps must contain a step with a "Score" output parameter (always a double) 
			//			   In this test we have only one step in the collection, so it must have both "Result" and "Score"

			TiXmlElement *OutputsXml = TinyXmlLib::CreateSection (procStepXml, ProcParamsOutputs::xmlOutputs, "CalcScore" );
			OutputsXml->SetAttribute("Count", 2);

			TiXmlElement *op1 = TinyXmlLib::CreateSection (OutputsXml, IPluginICProcStepsParamXmlProcParam, "0" );  //0 is the default value for "Result"
			op1->SetAttribute("Name", IPluginICProcStepsParamAttribOutputNameResult);		//IPluginICProcStepsParamAttribOutputNameResult is "Result"
			op1->SetAttribute("Index", 0);												//Result must be Index 0
			op1->SetAttribute("Type", "IntP");											//Result is Integer rather than Double ("DoubleP") or String ("StringP")
		
			TiXmlElement *op2 = TinyXmlLib::CreateSection (OutputsXml, IPluginICProcStepsParamXmlProcParam, "0.0" );	//0.0 is the default value for "Score"
			op2->SetAttribute("Name", IPluginICProcStepsParamAttribOutputNameScore);		//IPluginICProcStepsParamAttribOutputNameScore is "Score"
			op2->SetAttribute("Index", 1);												//Score must be Index 1
			op2->SetAttribute("Type", "DoubleP");										//Score is Double rather than Integer ("IntP") or String ("StringP")

			// 4. Initialise the collection of steps (_steps) from the ImageProcSteps section of the IEF 	

			Assert::IsTrue(_steps->LoadSteps(ief, Libs, TestFiles::UnitTestIntermediateImageFilewStr));	

			//******************************************************************************************
			// 5. Perform tests on _steps	
			//******************************************************************************************

			Assert::IsTrue( _steps->IsValid());					
			Assert::AreEqual(1, _steps->GetStepCount());		//1 valid step	

			//******************************************************************************************
			//	  End of tests on _steps
			//******************************************************************************************

			// 6. teardown the test 

			Assert::IsTrue(_steps->ClearAllSteps());
			Assert::IsTrue(Libs->ClearAllLibs());		//returns true if GetLibCount() > 0
			Assert::AreEqual( 0, Libs->GetLibCount());

			if (ief != '\0')
				delete ief;
		}

		TEST_METHOD(Load2StepsTest)
		{
			// 1. load  ImageProcSampleLib.dll from ImageProcStepsTest::ImageProcStepSampleLibPath (..\..\ThirdPartyLibs) - MUST BE IN PATH

			ImageProcStepLibs *Libs = '\0';
			Assert::IsNotNull(Libs = new ImageProcStepLibs());

			Assert::IsTrue( Libs->LoadLibs(TestFiles::UnitTestPluginDirwStr));
			Assert::AreEqual( 1, Libs->GetLibCount());		//ImageProcSampleLib.dll and ImageProcOpenCVLib.dll

			// 2. Create an Image Experiment File (IEF) called ImageExptLibTest::UnitTestIEFwStr () "UnitTestData\\Test.ief"

			ImageExpt *ief = '\0';

			Assert::IsNotNull(ief = ImageExpt::CreateImageExpt(TestFiles::UnitTestIEFwStr, '\0', L"unit test", L"default", ImageExpt::FromDefaults));
			Assert::IsTrue( ief->SaveFile());
			Assert::IsTrue( ImageExptLib::IsFileExist(TestFiles::UnitTestIEFwStr));
			Assert::IsNotNull(ief->GetHeaderProcSteps());

			TiXmlElement *procStepsXml = ief->GetHeaderProcSteps();
			procStepsXml->SetAttribute(ImageProcStepLibAuto::attribImageDllDir, TestFiles::UnitTestPluginDirStr);  
			procStepsXml->Clear();	//remove default analysis step

			// 3. Setup the ImageProcSteps section of the IEF so it contains the Step you want to test

			// 3a. Set the library details for the FIRST step - "CalcAvContrast"

			TiXmlElement *procStepXml1 = TinyXmlLib::CreateSection (procStepsXml, ImageProcStep::xmlProcStep, "(give description)" );
			procStepXml1->SetAttribute("StepNum", 0);						//this is the first step
			procStepXml1->SetAttribute("LibName", "ImageProcSample.dll");	//this is the library name - contains the function "CalcScore"
			procStepXml1->SetAttribute("LibVer", "v1.0.0.0");				//this is the library version - should match setting in "ImageProcSample.dll"
			procStepXml1->SetAttribute("IVer", 1);							//this is the library interface version - should match setting in "ImageProcSample.dll"

			// 3b. Set the name of a function in the above library - see ImageProcSampleLib.xml created when you run ImageProcSampleApp.exe
			//		<Step LibName="ImageProcSample.dll" LibVer="v1.0.0.0" IVer="1" Function="CalcAvContrast" AnalysisStep="yes">
		
			procStepXml1->SetAttribute("Function", "CalcAvContrast");				//name of the function that forms the step

			// 3c. Set the inputs for the above function name - see ImageProcSampleLib.xml created when you run ImageProcSampleApp.exe	
			//        <Inputs Count="1">CalcAvContrast
			//            <Param Name="contrast" Index="0" Type="DoubleP">50.0</Param>
			//        </Inputs>

			TiXmlElement *InputsXml1 = TinyXmlLib::CreateSection (procStepXml1, ProcParamsInputs::xmlInputs, "CalcAvContrast" );
			InputsXml1->SetAttribute("Count", 1);							//there is only 1 input param

			TiXmlElement *ip11 = TinyXmlLib::CreateSection (InputsXml1, IPluginICProcStepsParamXmlProcParam, "50" );
			ip11->SetAttribute("Name", "contrast");						
			ip11->SetAttribute("Index", 0);
			ip11->SetAttribute("Type", "DoubleP");

			// 3d. Set the outputs for the above function name - see ImageProcSampleLib.xml created when you run ImageProcSampleApp.exe
			//        <Outputs Count="1">CalcAvContrast
			//            <Param Name="Result" Index="0" Type="DoubleP">50.0</Param>
			//        </Outputs>
			//
			//  **** NOTE: Every step must have a "Result" output parameter and each collection of steps must contain a step with a "Score" output parameter (always double) 
			//			   In this test we have two steps in the collection, so this first step has just a "Result"

			TiXmlElement *OutputsXml1 = TinyXmlLib::CreateSection (procStepXml1, ProcParamsOutputs::xmlOutputs, "CalcAvContrast" );
			OutputsXml1->SetAttribute("Count", 1);

			TiXmlElement *op11 = TinyXmlLib::CreateSection (OutputsXml1, IPluginICProcStepsParamXmlProcParam, "0" );
			op11->SetAttribute("Name", IPluginICProcStepsParamAttribOutputNameResult);		//IPluginICProcStepsParamAttribOutputNameResult is "Result"
			op11->SetAttribute("Index", 0);												//Result must be Index 0
			op11->SetAttribute("Type", "DoubleP");										//Result is Double ("DoubleP") rather than Integer ("IntP") or String ("StringP")

			// 3e. Set the library details for the SECOND step -  "CalcScore" - the analysis step

			TiXmlElement *procStepXml2 = TinyXmlLib::CreateSection (procStepsXml, ImageProcStep::xmlProcStep, "(give description)" );
			procStepXml2->SetAttribute("StepNum", 1);						//this is the second step
			procStepXml2->SetAttribute("LibName", "ImageProcSample.dll");	//this is the library name - contains the function "CalcScore"
			procStepXml2->SetAttribute("LibVer", "v1.0.0.0");				//this is the library version - should match setting in "ImageProcSample.dll"
			procStepXml2->SetAttribute("IVer", 1);							//this is the library interface version - should match setting in "ImageProcSample.dll"

			// 3f. Set the name of a function in the above library - see ImageProcSampleLib.xml created when you run ImageProcSampleApp.exe
			//		<Step LibName="ImageProcSample.dll" LibVer="v1.0.0.0" IVer="1" Function="CalcScore" AnalysisStep="yes">
		
			procStepXml2->SetAttribute("Function", "CalcScore");				//name of the function that forms the step

			// 3c. Set the inputs for the above function name - see ImageProcSampleLib.xml created when you run ImageProcSampleApp.exe	
			//        <Inputs Count="1">CalcScore
			//            <Param Name="brightness" Index="0" Type="IntP">50</Param>
			//        </Inputs>

			TiXmlElement *InputsXml21 = TinyXmlLib::CreateSection (procStepXml2, ProcParamsInputs::xmlInputs, "CalcScore" );
			InputsXml21->SetAttribute("Count", 1);							//there is only 1 input param

			TiXmlElement *ip21 = TinyXmlLib::CreateSection (InputsXml21, IPluginICProcStepsParamXmlProcParam, "50" );
			ip21->SetAttribute("Name", "brightness");						//
			ip21->SetAttribute("Index", 0);
			ip21->SetAttribute("Type", "IntP");

			// 3d. Set the outputs for the above function name - see ImageProcSampleLib.xml created when you run ImageProcSampleApp.exe
			//        <Outputs Count="2">CalcScore
			//            <Param Name="Result" Index="0" Type="IntP">0</Param>
			//            <Param Name="Score" Index="1" Type="DoubleP">50.0</Param>
			//        </Outputs>
			//
			//  **** NOTE: Every step must have a "Result" output parameter and each collection of steps must contain a step with a "Score" output parameter (always a double) 
			//			   In this test we have two steps in the collection, so this second step must have both "Result" and "Score"

			TiXmlElement *OutputsXml2 = TinyXmlLib::CreateSection (procStepXml2, ProcParamsOutputs::xmlOutputs, "CalcScore" );
			OutputsXml2->SetAttribute("Count", 2);

			TiXmlElement *op21 = TinyXmlLib::CreateSection (OutputsXml2, IPluginICProcStepsParamXmlProcParam, "0" );
			op21->SetAttribute("Name", IPluginICProcStepsParamAttribOutputNameResult);		//IPluginICProcStepsParamAttribOutputNameResult is "Result"
			op21->SetAttribute("Index", 0);												//Result must be Index 0
			op21->SetAttribute("Type", "IntP");											//Result is Integer rather than Double ("DoubleP") or String ("StringP")

			TiXmlElement *op22 = TinyXmlLib::CreateSection (OutputsXml2, IPluginICProcStepsParamXmlProcParam, "0" );	//0.0 is the default value for result
			op22->SetAttribute("Name", IPluginICProcStepsParamAttribOutputNameScore);		//IPluginICProcStepsParamAttribOutputNameScore is "Score"
			op22->SetAttribute("Index", 1);												//Score must be Index 1
			op22->SetAttribute("Type", "DoubleP");										//Score is Double rather than Integer ("IntP") or String ("StringP")

			// 4. Initialise the collection of steps (_steps) from the ImageProcSteps section of the IEF 	

			Assert::IsTrue( _steps->LoadSteps(ief, Libs, TestFiles::UnitTestIntermediateImageFilewStr));		

			//******************************************************************************************
			// 5. Perform tests on _steps	
			//******************************************************************************************

			Assert::IsTrue( _steps->IsValid());		//2 valid steps				
			Assert::AreEqual( 2, _steps->GetStepCount());

			//******************************************************************************************
			//	  End of tests on _steps
			//******************************************************************************************

			// 6. teardown the test 

			Assert::IsTrue( _steps->ClearAllSteps());

			Assert::IsTrue( Libs->ClearAllLibs());		//returns true if GetLibCount() > 0
			Assert::AreEqual( 0, Libs->GetLibCount());

			if (ief != '\0')
				delete ief;

		}

		TEST_METHOD(LoadMissingStepsTest)
		{
			// 1. load  ImageProcSampleLib.dll from ImageProcStepsTest::ImageProcStepSampleLibPath (..\..\ThirdPartyLibs) - MUST BE IN PATH

			ImageProcStepLibs *Libs = '\0';
			Assert::IsNotNull(Libs = new ImageProcStepLibs());

			Assert::IsTrue(Libs->LoadLibs(TestFiles::UnitTestPluginDirwStr));
			Assert::AreEqual( 1, Libs->GetLibCount());		//ImageProcSampleLib.dll and ImageProcOpenCVLib.dll

			// 2. Create an Image Experiment File (IEF) called ImageExptLibTest::UnitTestIEFwStr () "UnitTestData\\Test.ief"

			ImageExpt *ief = '\0';

			Assert::IsNotNull(ief = ImageExpt::CreateImageExpt(TestFiles::UnitTestIEFwStr, '\0', L"unit test", L"default", ImageExpt::FromDefaults));
			Assert::IsTrue(ief->SaveFile());
			Assert::IsTrue(ImageExptLib::IsFileExist(TestFiles::UnitTestIEFwStr));
			Assert::IsNotNull(ief->GetHeaderProcSteps());

			TiXmlElement *procStepsXml = ief->GetHeaderProcSteps();
			procStepsXml->SetAttribute(ImageProcStepLibAuto::attribImageDllDir, TestFiles::UnitTestPluginDirStr);  
			procStepsXml->Clear();	//remove default analysis step

			// 3. Setup the ImageProcSteps section of the IEF so it contains the Step you want to test

			// 3a. Set the library details for the FIRST step - "CalcAvContrast"

			TiXmlElement *procStepXml1 = TinyXmlLib::CreateSection (procStepsXml, ImageProcStep::xmlProcStep, "(give description)" );
			procStepXml1->SetAttribute("StepNum", 0);						//this is the first step
			procStepXml1->SetAttribute("LibName", "ImageProcSample.dll");	//this is the library name - contains the function "CalcScore"
			procStepXml1->SetAttribute("LibVer", "v1.0.0.0");				//this is the library version - should match setting in "ImageProcSample.dll"
			procStepXml1->SetAttribute("IVer", 1);							//this is the library interface version - should match setting in "ImageProcSample.dll"

			// 3b. Set the name of a function in the above library - see ImageProcSampleLib.xml created when you run ImageProcSampleApp.exe
			//		<Step LibName="ImageProcSample.dll" LibVer="v1.0.0.0" IVer="1" Function="CalcAvContrast" AnalysisStep="yes">
		
			procStepXml1->SetAttribute("Function", "CalcAvContrast");				//name of the function that forms the step

			// 3c. Set the inputs for the above function name - see ImageProcSampleLib.xml created when you run ImageProcSampleApp.exe	
			//        <Inputs Count="1">CalcAvContrast
			//            <Param Name="contrast" Index="0" Type="DoubleP">50.0</Param>
			//        </Inputs>

			TiXmlElement *InputsXml1 = TinyXmlLib::CreateSection (procStepXml1, ProcParamsInputs::xmlInputs, "CalcAvContrast" );
			InputsXml1->SetAttribute("Count", 1);							//there is only 1 input param

			TiXmlElement *ip11 = TinyXmlLib::CreateSection (InputsXml1, IPluginICProcStepsParamXmlProcParam, "50" );
			ip11->SetAttribute("Name", "contrast");						
			ip11->SetAttribute("Index", 0);
			ip11->SetAttribute("Type", "DoubleP");

			// 3d. Set the outputs for the above function name - see ImageProcSampleLib.xml created when you run ImageProcSampleApp.exe
			//        <Outputs Count="1">CalcAvContrast
			//            <Param Name="Result" Index="0" Type="DoubleP">50.0</Param>
			//        </Outputs>
			//
			//  **** NOTE: Every step must have a "Result" output parameter and each collection of steps must contain a step with a "Score" output parameter (always double) 
			//			   In this test we have two steps in the collection, so this first step has just a "Result"

			TiXmlElement *OutputsXml1 = TinyXmlLib::CreateSection (procStepXml1, ProcParamsOutputs::xmlOutputs, "CalcAvContrast" );
			OutputsXml1->SetAttribute("Count", 1);

			TiXmlElement *op11 = TinyXmlLib::CreateSection (OutputsXml1, IPluginICProcStepsParamXmlProcParam, "0" );
			op11->SetAttribute("Name", IPluginICProcStepsParamAttribOutputNameResult);		//IPluginICProcStepsParamAttribOutputNameResult is "Result"
			op11->SetAttribute("Index", 0);												//Result must be Index 0
			op11->SetAttribute("Type", "DoubleP");										//Result is Double ("DoubleP") rather than Integer ("IntP") or String ("StringP")

			// 3e. Set the library details for the SECOND step -  "CalcScore" - the analysis step

			TiXmlElement *procStepXml2 = TinyXmlLib::CreateSection (procStepsXml, ImageProcStep::xmlProcStep, "(give description)" );
			//procStepXml2->SetAttribute("StepNum", 1);						//this is the second step
			procStepXml2->SetAttribute("LibName", "ImageProcSample.dll");	//this is the library name - contains the function "CalcScore"
			procStepXml2->SetAttribute("LibVer", "v1.0.0.0");				//this is the library version - should match setting in "ImageProcSample.dll"
			procStepXml2->SetAttribute("IVer", 1);							//this is the library interface version - should match setting in "ImageProcSample.dll"

			// 3f. Set the name of a function in the above library - see ImageProcSampleLib.xml created when you run ImageProcSampleApp.exe
			//		<Step LibName="ImageProcSample.dll" LibVer="v1.0.0.0" IVer="1" Function="CalcScore" AnalysisStep="yes">
		
			procStepXml2->SetAttribute("Function", "CalcScore");				//name of the function that forms the step

			// 3c. Set the inputs for the above function name - see ImageProcSampleLib.xml created when you run ImageProcSampleApp.exe	
			//        <Inputs Count="1">CalcScore
			//            <Param Name="brightness" Index="0" Type="IntP">50</Param>
			//        </Inputs>

			TiXmlElement *InputsXml21 = TinyXmlLib::CreateSection (procStepXml2, ProcParamsInputs::xmlInputs, "CalcScore" );
			InputsXml21->SetAttribute("Count", 1);							//there is only 1 input param

			TiXmlElement *ip21 = TinyXmlLib::CreateSection (InputsXml21, IPluginICProcStepsParamXmlProcParam, "50" );
			ip21->SetAttribute("Name", "brightness");						//
			ip21->SetAttribute("Index", 0);
			ip21->SetAttribute("Type", "IntP");

			// 3d. Set the outputs for the above function name - see ImageProcSampleLib.xml created when you run ImageProcSampleApp.exe
			//        <Outputs Count="2">CalcScore
			//            <Param Name="Result" Index="0" Type="IntP">0</Param>
			//            <Param Name="Score" Index="1" Type="DoubleP">50.0</Param>
			//        </Outputs>
			//
			//  **** NOTE: Every step must have a "Result" output parameter and each collection of steps must contain a step with a "Score" output parameter (always a double) 
			//			   In this test we have two steps in the collection, so this second step must have both "Result" and "Score"

			TiXmlElement *OutputsXml2 = TinyXmlLib::CreateSection (procStepXml2, ProcParamsOutputs::xmlOutputs, "CalcScore" );
			OutputsXml2->SetAttribute("Count", 2);

			TiXmlElement *op21 = TinyXmlLib::CreateSection (OutputsXml2, IPluginICProcStepsParamXmlProcParam, "0" );
			op21->SetAttribute("Name", IPluginICProcStepsParamAttribOutputNameResult);		//IPluginICProcStepsParamAttribOutputNameResult is "Result"
			op21->SetAttribute("Index", 0);												//Result must be Index 0
			op21->SetAttribute("Type", "IntP");											//Result is Integer rather than Double ("DoubleP") or String ("StringP")

			TiXmlElement *op22 = TinyXmlLib::CreateSection (OutputsXml2, IPluginICProcStepsParamXmlProcParam, "0" );	//0.0 is the default value for result
			op22->SetAttribute("Name", IPluginICProcStepsParamAttribOutputNameScore);		//IPluginICProcStepsParamAttribOutputNameScore is "Score"
			op22->SetAttribute("Index", 1);												//Score must be Index 1
			op22->SetAttribute("Type", "DoubleP");										//Score is Double rather than Integer ("IntP") or String ("StringP")

			// 4. Initialise the collection of steps (_steps) from the ImageProcSteps section of the IEF 	

	
			//******************************************************************************************
			// 5. Perform tests on _steps	
			//******************************************************************************************

			Assert::IsFalse( _steps->LoadSteps(ief, Libs, TestFiles::UnitTestIntermediateImageFilewStr));		
			Assert::IsFalse( _steps->IsValid());		//missing step 1

			procStepXml2->SetAttribute("StepNum", 0);
			Assert::IsFalse(_steps->LoadSteps(ief, Libs, TestFiles::UnitTestIntermediateImageFilewStr));		
			Assert::IsFalse(_steps->IsValid());		//duplicate step 1
			Assert::IsTrue( _steps->ClearAllSteps());

			procStepXml2->SetAttribute("StepNum", 1);
			Assert::IsTrue(_steps->LoadSteps(ief, Libs, TestFiles::UnitTestIntermediateImageFilewStr));		
			Assert::IsTrue(_steps->IsValid());		//OK

			Assert::AreEqual( 2, _steps->GetStepCount());

			//******************************************************************************************
			//	  End of tests on _steps
			//******************************************************************************************

			// 6. teardown the test 

			Assert::IsTrue(_steps->ClearAllSteps());
			Assert::IsTrue(Libs->ClearAllLibs());		//returns true if GetLibCount() > 0
			Assert::AreEqual( 0, Libs->GetLibCount());

			if (ief != '\0')
				delete ief;
		}
	};
}

